package com.tools.service.user.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tools.common.enums.ResultCode;
import com.tools.common.exception.BusinessException;
import com.tools.mapper.user.MenuMapper;
import com.tools.pojo.user.dto.MenuDTO;
import com.tools.pojo.user.po.Menu;
import com.tools.pojo.user.vo.MenuVO;
import com.tools.service.user.MenuService;
import com.tools.utils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {



    @Override
    public List<MenuVO> tree() {
        List<Menu> menus = baseMapper.selectList(new LambdaQueryWrapper<Menu>()
                .orderByAsc(Menu::getSort));
        return buildTree(menus, null) == null ? Collections.emptyList() : buildTree(menus, null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveMenu(MenuDTO menuDTO) {
        checkMenuUnique(menuDTO);
        Menu menu = BeanUtils.copyProperties(menuDTO, Menu.class);
        return save(menu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMenu(MenuDTO menuDTO) {
        checkMenuUnique(menuDTO);
        Menu menu = BeanUtils.copyProperties(menuDTO, Menu.class);
        return updateById(menu);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeMenu(Long id) {
        return removeById(id);
    }

    @Override
    public IPage<MenuVO> getPageList(MenuDTO menuDTO) {
        IPage<Menu> page = new Page<>(menuDTO.getCurrent(), menuDTO.getSize());
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByAsc(Menu::getSort);
        wrapper.eq(StringUtils.isNotBlank(menuDTO.getStatus()), Menu::getStatus, menuDTO.getStatus());
        wrapper.like(StringUtils.isNotBlank(menuDTO.getName()), Menu::getName, menuDTO.getName());
        wrapper.eq(StringUtils.isNotBlank(menuDTO.getType()), Menu::getType, menuDTO.getType());
        IPage<Menu> pageList = this.page(page, wrapper);
        return pageList.convert(m -> BeanUtils.copyProperties(m, MenuVO.class));
    }

    @Override
    public MenuVO getMenuDetailById(Long id) {
        Menu menu = getById(id);
        if (menu == null) {
            throw new BusinessException(ResultCode.DATA_QUERY_ERROR, "菜单不存在");
        }
        return BeanUtils.copyProperties(menu, MenuVO.class);
    }

    @Override
    public List<MenuVO> getMenuList(MenuDTO menuDTO) {
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByAsc(Menu::getSort);
        wrapper.eq(StringUtils.isNotBlank(menuDTO.getStatus()), Menu::getStatus, menuDTO.getStatus());
        wrapper.like(StringUtils.isNotBlank(menuDTO.getName()), Menu::getName, menuDTO.getName());
        wrapper.eq(StringUtils.isNotBlank(menuDTO.getType()), Menu::getType, menuDTO.getType());
        List<Menu> menus = baseMapper.selectList(wrapper);
        return menus.stream().map(m -> BeanUtils.copyProperties(m, MenuVO.class)).collect(Collectors.toList());
    }

    /**
     * 构建菜单树
     * @param menus 菜单列表
     * @param parentId 父菜单ID
     * @return 菜单树
     */
    private List<MenuVO> buildTree(List<Menu> menus, Long parentId) {
        return menus.stream()
                .filter(m ->
                    (parentId == null && (m.getParentId() == null || m.getParentId() == 0L)) || // 处理父节点为空的情况
                    (parentId != null && parentId.equals(m.getParentId())) // 原有判断逻辑
                )
                .map(m -> {
                    MenuVO vo = BeanUtils.copyProperties(m, MenuVO.class);
                    vo.setChildren(buildTree(menus, m.getId()));
                    return vo;
                }).collect(Collectors.toList());
    }

    /**
     * 检查菜单名称或权限标识是否唯一
     * @param menuDTO 菜单BO
     */
    private void checkMenuUnique(MenuDTO menuDTO) {
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.ne(menuDTO.getId() != null, Menu::getId, menuDTO.getId())
                .and(w -> w.eq(Menu::getName, menuDTO.getName())
                        .or().eq(StringUtils.isNotBlank(menuDTO.getPermission()),
                                Menu::getPermission, menuDTO.getPermission()));

        if (count(wrapper) > 0) {
            throw new BusinessException(ResultCode.DATA_EXIST, "菜单名称或权限标识已存在");
        }
    }


}
